#! /usr/bin/env python
# -*- coding: utf-8 -*-

import socket
import re
import os
import time
import random
import traceback

import FileHostProtoType

class buitem(FileHostProtoType.HostItem):
    def __init__(self, name, type, id, link, encrypt_name='', server_name=''):  
        FileHostProtoType.HostItem.__init__(self, name, type, id, link, encrypt_name, server_name)

class uploading(FileHostProtoType.FileHostProcess):
    def __init__(self,user,pwd):
        FileHostProtoType.FileHostProcess.__init__(self)
        self.hostname = "uploading.com"
        self._opener = None
        self._cj = None
        self._user = user
        self._pwd = pwd
        self.islogin = False
            
    def login(self):
        '''
        login to FileSonic
        return opener object which includes cookies
        '''
        self.generateOpener()
        if self.islogin == True:
            return True
        self.fherr.write('login to uploading.com %s/%s...' % (self._user,'*'*len(self._pwd)))
        loginData = {'email' : self._user,
                'password' : self._pwd,
                'remember' : 'on' }
        index_page = self.post_request("http://uploading.com/").encode('utf-8')
        sid = self.find_SID(index_page)
        timeticket = self.get_timeticket(bits=14) 
        print timeticket
        for x in self._cj:
            print x
        login_url = "http://uploading.com/general/login_form/"
        print login_url
        print loginData
        response = self.loginFileHost(login_url,loginData)
        #print(response)
        resp = self.post_request('http://uploading.com/profile/')
        if self._user in resp:
            print("Yes!")
        # user info can be found in cookie
        if 'error' in response:
            self.fherr.write("User %s Failed to Login Uploading.com." % self._user)
            return False
        self.fherr.write("User %s logined to Uploading.com." % self._user)
        self.islogin = True
        return self.islogin
    
    def find_SID(self, page):
        sid_pos = page.find("SID: '")
        sid = page[sid_pos+6:sid_pos+6+32]
        return sid
        
    def getFileList(self):
        return self.exportLinks()
    
    def getFilesFromFolder(self, folder):
        id  = folder.id
        return self.exportLinks(id[1:])
    
    def exportLinks(self, id=-1):
        url = "http://www%s/file-manager/export-all-links/%s/csv" % (self.domain, id)
        response = self.post_request(url)
        return self.pasterItemFromCSV(response)
    
    def pasterItemFromCSV(self, csvdata):
        fileList = []
        itemLines = csvdata.split('\n')
        itemLines.pop(0)
        for itemLine in itemLines:
            if not itemLine.strip():
                continue
            itemTokens = itemLine.split(';')
            name = itemTokens[1]
            id = 'F' + itemTokens[0]
            type = 'file'
            link = itemTokens[3]
            item = buitem(name, type, id, link)
            fileList.append(item)
        fileList.sort()
        return fileList
    
    def getFolderList(self):   
        url = "http://www%s/file-manager/list" % self.domain
        response = self.post_request(url)
        reFolder = re.compile('CMApplication\.Widgets\.FileManager\.Items\.add\((?P<json>.*?)\);')
        matchResult = reFolder.search(response)
        foundFolders = []
        if matchResult is not None:
            folder_json = matchResult.group('json')
            folder_dict = {}
            exec("folder_dict=%s" % folder_json)
            #take care for no folder in account
            if folder_dict:
                for id, data in folder_dict.iteritems():
                    link = "http://www.wupload.com/folder/%s" % data['id']
                    item = buitem(data['name'], 'folder', id, link)
                    foundFolders.append(item)
        foundFolders.sort()
        return foundFolders 
    
    def find(self, filenames=[], filelist=None):
        '''
        open the filelist page according to opener with cookies
        '''
        found = []
        if filelist is None:
            filelist = self.getFileList()        
        filelistlower = [fl.name.lower() for fl in filelist]
        todel = []
        for fl in filenames:
            try:
                index = filelistlower.index(os.path.basename(fl).lower())
                found.append(filelist[index])
                todel.append(fl)
            except:
                continue
        for d in todel:
            filenames.remove(d)
        found.sort()
        return found

    def findFolder(self, foldername):        
        folders = self.getFolderList()
        for f in folders:
            if foldername == f.name:
                return f
        return None

    def createFolder(self, newfolder):
        foundfolder = self.findFolder(newfolder)
        if foundfolder is None:
            #wupload no longer allow user to create subdir 
            return self.__newFolder(newfolder)
        self.fherr.write("Folder %s exsits." % newfolder)
        return foundfolder

    def __newFolder(self, newfolder, parentfolder=None):
        '''
        newfolder : without any '/',just a standard folder name
        '''
        data =[]
        pid = 'D0'
        if parentfolder is not None:
            pid = parentfolder.id
        data.append(('can_access_parent', '0'))
        data.append(('is_public', '1'))
        data.append(('id', ''))
        data.append(('description', ''))
        data.append(('name', newfolder))
        data.append(('parent_folder_id', pid))  
        url = "http://www%s/file-manager/create/D0" % self.domain
        self.fherr.write("Creating folder %s ..." % newfolder)
        while(1):            
            self.post_request(url, data, retry=1)
            time.sleep(2)
            newItem = self.findFolder(newfolder)
            if newItem is not None:
                return newItem
    
    def moveto(self, items, destFolder):
        if len(items) == 0:
            return
        url = "http://www%s/file-manager/move/:id" % self.domain
        data = []
        for i in items:
            data.append(('files[]',i.id))        
        data.append(('destination',destFolder.id))
        self.post_request(url, data)
        files = self.getFilesFromFolder(destFolder)        
        for i in items:
            if i in files:
                self.fherr.write("%s has been moved to %s." % (i.name, destFolder.name))
            else:
                self.fherr.write("Fail to move %s to %s" % (i.name, destFolder.name))
    
    def upload_web(self, file, progressLog=None, other_args=None):
        return self.upload_web_local(file, progressLog, other_args)
    
    def upload_web_local(self, file, progressLog=None, other_args=None):
        #upload page           
        uploadpage = self.post_request("http://www%s/" % self.domain).encode('utf8', 'ignore')
        
        sessid = ''
        for cookie in self._cj:
            if cookie.name == 'PHPSESSID':
                sessid = cookie.value
                
        serverlink = 'web.eu.wupload.com'
        '''
        reServer = re.compile('(?P<serverlink>s(?P<id>\d+)%s)' % self.domain)
        serverMatch = reServer.search(uploadpage)
        if serverMatch is not None:
            serverlink = "http://" + serverMatch.group("serverlink")
        else:
            self.fherr.write('Failed to get serverlink')
            return
        '''
            
        timetick = int(time.time()*1000)
        randomnumber = int(random.random()*90000)
        
        ProgressID = "upload_%d_%s_%d" % (timetick, sessid, randomnumber)
        
        data = {}
        data["callbackUrl"] = "http://www%s/upload/done/:uploadProgressId" % self.domain
        data['X-Progress-ID'] = ProgressID
        data['folderID'] = '0'
        data['files[1]'] = open(file,'rb')
        
        callback = None
        if progressLog is not None:
            callback = progressLog.write
        
        self.fherr.write("Uploading...%s" % file)        
        resultMsg = self.post_file(serverlink, \
                                   data, \
                                   self.get_cookies(), \
                                   callback=callback)
        if resultMsg is None:
            self.fherr.write("UploadTask(%s) was Stop by user." % file)
            return

        resultMsg = resultMsg.split('\n')
        for line in resultMsg:
            if line.startswith("data") ==  True:
                line = line.strip().replace("null",'""')
                exec(line)                
                linkid = data['1']['linkId']
                link = "http://www.wupload.com/file/%s" %(linkid[1:])
                server_name = data['1']['link']['name']   
                exec('server_name=u"%s"' % server_name) 
                #output original filename instead of wupload's new name
                ori_name = os.path.basename(file)
                item = buitem(ori_name, 'file', linkid, link, self.rename_func(file), server_name)
                self.fherr.write(item.format())
                self.newupload.append(item)
                return item
            
        self.fherr.write('\n'.join(resultMsg))
        self.fherr.write("Fail to get link from uploadresponse, Try to find it in file manager...")
        #find new upload file:
        time.sleep(30)
        times = self.wait_time/60 + 1
        target_name = self.rename_func(file)
        while times > 0:            
            root = buitem('root','/root','D0','')
            rootfiles = self.getFilesFromFolder(root)
            find_result = self.find([target_name,], rootfiles)
            if find_result:
                new_file = find_result[0]     
                item = buitem(os.path.basename(file), \
                              'file', \
                              new_file.id, \
                              new_file.link, \
                              target_name,\
                              new_file.server_name)
                self.newupload.append(item)
                return item
            times -= 1
            time.sleep(60)
            
        self.fherr.write("Fail to get link in file manager, Wait for 1min and ReUpload...")
        
        return
    
    def upload_to_ftp(self, file, progressLog=None, other_args=None):
        host = 'ftp.wupload.com'
        ips = []
        for addrinfo in socket.getaddrinfo(host, 21):
            ips.append(addrinfo[4][0])
            
        userpwd = ('%s:%s' % (self._user, self._pwd)).encode('utf8')
        target_name = self.rename_func(file)
        callback = None
        if progressLog is not None:
            callback = progressLog.write

        retry = 10
        while retry > 0:
            ip = ips[random.randint(0,len(ips)-1)]
            url = 'ftp://%s' % ip 
            self.fherr.write("Uploading...%s to %s" % (file, url))
            try:
                self.upload_file_to_ftp(url, userpwd, file, \
                                target=target_name.encode('utf8'), \
                                callback=callback)
            except:
                self.fherr.write(traceback.format_exc())
                time.sleep(60)
                retry -= 1
                continue
            break
        if retry == 0:
            self.fherr.write('max retry. failed')
            return
        
        
        #find new upload file:
        time.sleep(30)
        times = self.wait_time/60 + 1
        while times > 0:            
            root = buitem('root','/root','D0','')
            rootfiles = self.getFilesFromFolder(root)
            find_result = self.find([target_name,], rootfiles)
            if find_result:
                new_file = find_result[0]     
                item = buitem(os.path.basename(file), \
                              'file', \
                              new_file.id, \
                              new_file.link, \
                              target_name,\
                              new_file.server_name)
                self.newupload.append(item)
                return item
            times -= 1
            time.sleep(60)


if __name__ == "__main__":
    pass